package com.haiyou.crawler;

import com.alibaba.fastjson.JSON;
import com.haiyou.crawler.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.cookie.Cookie;
import us.codecraft.webmagic.selector.Html;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author chenzeke
 * @date 2019/11/28 22:23
 */
@Slf4j
public class SteamSpyCrawlerStrategy {
    private static String testUrl = "https://steamspy.com/api.php?request=appdetails&appid=1";
    private static String indexUrl = "https://steamspy.com";
    private static String action = "";
    private static String id = "";
    private static String r = "";
    private static String jschlVc = "";
    private static String pass = "";
    private static String jschlAnswer = "";
    private static String sessionStr = "";
    private static String captchaCode = "";
    private static HttpSession httpSession = new HttpSession();
    private static HashMap<String, String> headers;

    public static synchronized void init() {

        try {
            headers = new HashMap<>();
            headers.put("Upgrade-Insecure-Requests", "1");
            headers.put("Content-Type", "application/x-www-form-urlencoded");
            headers.put("User-Agent", SteamSpyConstant.USER_AGENT);
            headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
            headers.put("Accept-Language", "deflate, br");
            headers.put("Accept-Encoding", "zh-CN,zh;q=0.9");
            if (getSteamSpyUrl()) {
                getActionUrl();
                getSessionStr();
                getImageCode();
                getLastUrl();
            } else {
                log.info("不需要更新，执行测试数据====>" + getData(testUrl));
            }
        } catch (Exception e) {
            log.error("初始化异常====>" + e.getMessage(), e);
        }

    }

    /**
     * 1. 访问首页
     *
     * @throws Exception
     */
    public static boolean getSteamSpyUrl() throws Exception {
        //首页
        HttpClientResult httpClientResult = httpSession.doGet(indexUrl, headers, null);
        if (StringUtil.isCheck(httpClientResult.getContent())) {
            //返回内容
            Html html = new Html(httpClientResult.getContent());
            r = html.xpath("//form[@id='challenge-form']/input[@name='r']/@value").get();
            jschlVc = html.xpath("//form[@id='challenge-form']/input[@name='jschl_vc']/@value").get();
            pass = html.xpath("//form[@id='challenge-form']/input[@name='pass']/@value").get();
            action = html.xpath("//form[@id='challenge-form']/@action").get();
            String id = html.xpath("//span[@class='ray_id']/code/html()").get();
            if (!StringUtil.isEmpty(id)) {
                log.info("SteamSpyCrawlerStrategy.id====>" + SteamSpyCrawlerStrategy.id);
                log.info("id===>" + id);
                SteamSpyCrawlerStrategy.id = id;
            }
            String id2 = html.xpath("//span[@class='yjs-footer-item']/strong/html()").get();
            if (!StringUtil.isEmpty(id2)) {
                log.info("SteamSpyCrawlerStrategy.id====>" + SteamSpyCrawlerStrategy.id);
                log.info("id2===>" + id2);
                SteamSpyCrawlerStrategy.id = id2;
            }
            log.info("r=" + r);
            log.info("jschlVc=" + jschlVc);
            log.info("pass=" + pass);
            log.info("action=" + action);
//            log.info("html=" + html);
            jschlAnswer = getJschlAnswer(html.toString());
            Thread.sleep(5000);
            return true;
        }
        log.info("session不需要更新===>" + httpClientResult.getContent().length());
        return false;
    }

    /**
     * 2. 带参数提交表单
     *
     * @throws Exception
     */
    public static void getActionUrl() throws Exception {
        String url2 = indexUrl + action;
        log.info("------->url2={}", url2);
        Map<String, String> params = new HashMap<>();
        params.put("r", r);
        params.put("jschl_vc", jschlVc);
        params.put("pass", pass);
        params.put("jschl_answer", jschlAnswer);
        HttpClientResult httpClientResult = httpSession.doPost(url2, headers, params);
        Html html = new Html(httpClientResult.getContent());
        action = html.xpath("//form[@id='challenge-form']/@action").get();
        String id = html.xpath("//span[@class='ray_id']/code/html()").get();
        if (!StringUtil.isEmpty(id)) {
            log.info("SteamSpyCrawlerStrategy.id====>" + SteamSpyCrawlerStrategy.id);
            log.info("id===>" + id);
            SteamSpyCrawlerStrategy.id = id;
        }
        String id2 = html.xpath("//span[@class='yjs-footer-item']/strong/html()").get();
        if (!StringUtil.isEmpty(id2)) {
            log.info("SteamSpyCrawlerStrategy.id====>" + SteamSpyCrawlerStrategy.id);
            log.info("id2===>" + id2);
            SteamSpyCrawlerStrategy.id = id2;
        }
    }

    /**
     * 3. 获取sessionStr
     *
     * @throws Exception
     */
    public static void getSessionStr() throws Exception {
        String url3 = "https://captcha.su.baidu.com/session_cb/?pub=377e4907e1a3b419708dbd00df9e8f79&callback=callback";
        HttpClientResult httpClientResult = httpSession.doGet(url3, headers, null);
        sessionStr = getSubString(httpClientResult.getContent(), "sessionstr\":\"", "\"");
    }

    /**
     * 4. 获取验证码
     *
     * @throws Exception
     */
    public static void getImageCode() throws Exception {
        String url4 = "https://captcha.su.baidu.com/image?session=" + sessionStr + "&pub=377e4907e1a3b419708dbd00df9e8f79";
        captchaCode = HttpUtil.doGetImage(url4);
    }

    public static void getLastUrl() throws Exception {
        String url5 = indexUrl + action;
        if (StringUtil.isEmpty(action)) {
            url5 = indexUrl;
        }
        Map<String, String> params = new HashMap<>();
        params.put("r", r);
        params.put("id", id);
        params.put("captcha_challenge_field", sessionStr);
        params.put("manual_captcha_challenge_field", captchaCode);
        log.info("----->params={}", JSON.toJSONString(params));
        HttpClientResult httpClientResult = httpSession.doPost(url5, headers, params);
        String data = getData(testUrl);
        log.info("测试数据是否正确===>" + data);
        printCookie();
    }

    public static void printCookie() {
        for (int i = 0; i < httpSession.cookieStore.getCookies().size(); i++) {
            Cookie cookie = httpSession.cookieStore.getCookies().get(i);
            log.info("cookie========>" + JSON.toJSONString(cookie));
        }
    }

    public static String getJschlAnswer(String html) {
        String result = null;
        String sp1 = "function(p){var p ";
        String sp2 = "return +(p)}();";
        String p1 = sp1 + getSubString(html, sp1, sp2) + sp2;
        String sp3 = "+(function(p)";
        String sp4 = ");";
        String p2 = sp3 + getSubString(html, sp3, sp4) + sp4;

        String p22 = "eval(" + getSubString(p2, "eval(", "\"(\"+p+\")\")}") + "\"(\"+p+\")\")}";
        String p2Result = "t.charCodeAt(p)}";
        Html obj = new Html(html);
        String s1 = obj.xpath("//div[@style='display:none;visibility:hidden;]/html()").get();
        try {
            String subString = "function getJschl_answer(){" + getSubString(html, "setTimeout(function(){", "'; 121'");
            log.info("原始js===>" + subString);
            subString = subString.replace("t = document.createElement('div');", "");
            subString = subString.replace("t.innerHTML=\"<a href='/'>x</a>\";", "");
            subString = subString.replace("t.firstChild.href", "\"http://steamspy.com/\"");
            subString = subString.replace("a = document.getElementById('jschl-answer');", "a = {}");
            subString = subString.replace("f = document.getElementById('challenge-form');", "");
            subString = subString.replace(p1, s1 + ";");
            subString = subString.replace(p22, p2Result);
            subString += "return a.value } getJschl_answer()";
            ScriptEngineManager m = new ScriptEngineManager();
            ScriptEngine engine = m.getEngineByName("JavaScript");
            result = (String) engine.eval(subString);
            log.info("结果js===>" + subString);
            log.info("js计算结果为===>" + result);
        } catch (ScriptException e) {
            log.info(e.getMessage(), e);
        }
        return result;
    }

    public static String getSubString(String text, String left, String right) {
        String result = "";
        int zLen;
        if (left == null || left.isEmpty()) {
            zLen = 0;
        } else {
            zLen = text.indexOf(left);
            if (zLen > -1) {
                zLen += left.length();
            } else {
                zLen = 0;
            }
        }
        int yLen = text.indexOf(right, zLen);
        if (yLen < 0 || right.isEmpty()) {
            yLen = text.length();
        }
        result = text.substring(zLen, yLen);
        return result;
    }

    public static String getData(String url) {
        try {
            HttpClientResult httpClientResult = httpSession.doGet(url, headers, null);
            return httpClientResult.getContent();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

}
